package com.dsdl.chatapp.common.db;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.dsdl.chatapp.BaseApplication;
import com.dsdl.chatapp.data.SocketMessage;
import com.dsdl.chatapp.data.source.local.ChatPersistenceContract;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by zzg on 2016/9/2.
 */
public class ChatDAO implements IChatDAO{
    private SQLiteDatabase mDataBase;
    private Lock mLock = new ReentrantLock();
    private static volatile ChatDAO mChatDAO;

    private ChatDAO(Context context){
        DBHelper dbHelper = new DBHelper(context);
        mDataBase = dbHelper.getWritableDatabase();
    }

    public static synchronized ChatDAO getInstance() {
        mChatDAO = new ChatDAO(BaseApplication.getInstance());
        return mChatDAO;
    }

    @Override
    public SQLiteDatabase getDatabase() {
        return mDataBase;
    }

    @Override
    public long insert(ContentValues values) {
        try{
            mChatDAO.lock();
            openDB();
            if (mDataBase != null){
                return mDataBase.insert(ChatPersistenceContract.ChatEntry.TABLE_NAME,null,values);
            }
        }finally {
            closeDB();
            mChatDAO.unLock();
        }
        return 0;
    }

    @Override
    public int delete(String whereClause, String[] whereArgs) {
        try{
            mChatDAO.lock();
            openDB();
            if (mDataBase != null){
                return mDataBase.delete(ChatPersistenceContract.ChatEntry.TABLE_NAME,whereClause,whereArgs);
            }
        }finally {
            closeDB();
            mChatDAO.unLock();
        }
        return 0;
    }

    @Override
    public void deleteById(int id) {
        try{
            mChatDAO.lock();
            openDB();
            if (mDataBase != null){
                mDataBase.delete(ChatPersistenceContract.ChatEntry.TABLE_NAME,"_id = ?",new String[]{String.valueOf(id)});
            }
        }finally {
            closeDB();
            mChatDAO.unLock();
        }
    }

    @Override
    public int deleteAllByUserId(String userId) {
        try{
            mChatDAO.lock();
            openDB();
            if (mDataBase != null){
                return mDataBase.delete(ChatPersistenceContract.ChatEntry.TABLE_NAME,ChatPersistenceContract.ChatEntry.COLUMN_NAME_FROM_USER+" = ? OR "+ChatPersistenceContract.ChatEntry.COLUMN_NAME_TO_USER+" = ?",new String[]{userId,userId});
            }
        }finally {
            closeDB();
            mChatDAO.unLock();
        }
        return 0;
    }

    @Override
    public long update(ContentValues values, String whereClause, String[] whereArgs) {
        try{
            mChatDAO.lock();
            openDB();
            if (mDataBase != null){
                return mDataBase.update(ChatPersistenceContract.ChatEntry.TABLE_NAME,values,whereClause,whereArgs);
            }
        }finally {
            closeDB();
            mChatDAO.unLock();
        }
        return 0;
    }

    @Override
    public long insertOrUpdate(ContentValues values, String whereClause, String[] whereArgs) {
        Cursor cursor = null;
        try{
            mChatDAO.lock();
            openDB();
            cursor = mDataBase.query(ChatPersistenceContract.ChatEntry.TABLE_NAME,null,whereClause,whereArgs,null,null,null,null);
            if (cursor.getCount() > 0){
                if (mDataBase != null){
                    return mDataBase.update(ChatPersistenceContract.ChatEntry.TABLE_NAME,values,whereClause,whereArgs);
                }
            }else {
                if (mDataBase != null){
                    return mDataBase.insert(ChatPersistenceContract.ChatEntry.TABLE_NAME,null,values);
                }
            }

        }finally {
            if (cursor != null){
                cursor.close();
                cursor = null;
            }
            closeDB();
            mChatDAO.unLock();
        }
        return 0;
    }

    @Override
    public List<SocketMessage> rawQuery(String sql, String[] selectionArgs) {
        Cursor cursor = null;
        try{
            mChatDAO.lock();
            openDB();
            if (mDataBase != null){
                cursor = mDataBase.rawQuery(sql,selectionArgs);
                return setColumnData(cursor);
            }
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            if (cursor != null){
                cursor.close();
            }
            closeDB();
            mChatDAO.unLock();
        }
        return null;
    }

    @Override
    public List<SocketMessage> query(String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) {
        Cursor cursor = null;
        try{
            mChatDAO.lock();
            openDB();
            if (mDataBase != null){
                cursor = mDataBase.query(ChatPersistenceContract.ChatEntry.TABLE_NAME, columns, selection, selectionArgs, groupBy, having, orderBy, limit);
                return setColumnData(cursor);
            }
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            if (cursor != null){
                cursor.close();
            }
            closeDB();
            mChatDAO.unLock();
        }
        return null;
    }

    @Override
    public List<SocketMessage> queryAll(String selection, String[] selectionArgs, String orderBy) {
        Cursor cursor = null;
        try{
            mChatDAO.lock();
            openDB();
            if (mDataBase != null){
                cursor = mDataBase.query(ChatPersistenceContract.ChatEntry.TABLE_NAME, null, selection, selectionArgs, null, null, orderBy, null);
                return setColumnData(cursor);
            }
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            if (cursor != null){
                cursor.close();
            }
            closeDB();
            mChatDAO.unLock();
        }
        return null;
    }

    /**
     * 锁数据库
     */
    private void lock() {
        if (mLock == null){
            mLock = new ReentrantLock();
        }
        mLock.lock();
    }

    /**
     * 解锁数据库
     */
    private void unLock() {
        if (mLock == null){
            return;
        }
        mLock.unlock();
    }

    /**
     * 打开数据库
     */
    private void openDB() {
        if (mDataBase != null && mDataBase.isOpen()){
            return;
        }
        DBHelper dbHelper = new DBHelper(BaseApplication.getInstance());
        mDataBase = dbHelper.getWritableDatabase();
    }

    /**
     * 关闭数据库
     */
    private void closeDB() {
        if (mDataBase != null) {
            mDataBase.close();
            mDataBase = null;
        }
    }

    private List<SocketMessage> setColumnData(Cursor cursor){
        List<SocketMessage> list = new ArrayList<>();
        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
            SocketMessage socketMessage = new SocketMessage();
            socketMessage.setCreateTime(Long.parseLong(cursor.getString(cursor.getColumnIndex(ChatPersistenceContract.ChatEntry.COLUMN_NAME_CREATE_TIME))));
            socketMessage.setMsgType(cursor.getString(cursor.getColumnIndex(ChatPersistenceContract.ChatEntry.COLUMN_NAME_MSG_TYPE)));
            socketMessage.setContent(cursor.getString(cursor.getColumnIndex(ChatPersistenceContract.ChatEntry.COLUMN_NAME_CONTENT)));
            socketMessage.setToUser(cursor.getString(cursor.getColumnIndex(ChatPersistenceContract.ChatEntry.COLUMN_NAME_TO_USER)));
            socketMessage.setFromUser(cursor.getString(cursor.getColumnIndex(ChatPersistenceContract.ChatEntry.COLUMN_NAME_FROM_USER)));
            list.add(socketMessage);
        }
        return list;
    }
}
